import { IsDebug } from "./util"

//Node对象池
export class NodePool {
    private static _instance: NodePool = null
    public static getInstance(): NodePool {
        if (NodePool._instance == null) {
            NodePool._instance = new NodePool()
        }
        return NodePool._instance
    }

    constructor() {
        this._nodePools = new Object()
    }

    private _nodePools: any
    private getNodePool(prefabPath: string): Array<cc.Node> {
        let pool = this._nodePools[prefabPath]
        if (!pool) {
            pool = new Array<cc.Node>()
            this._nodePools[prefabPath] = pool
        }
        return pool
    }

    public putNodeIntoPool(prefabPath: string, node: cc.Node) {
        if (prefabPath.length == 0) {
            return
        }
        let pool = this.getNodePool(prefabPath)
        node.emit("unuse")
        node.active = false
        pool.push(node)
        if (!node.parent) {
        }
    }

    public getNodeFromPool(prefabPath: string): cc.Node {
        let pool = this.getNodePool(prefabPath)
        if (pool.length > 0) {
            let node = pool.shift()
            node.active = true
            node.emit("reuse")
            if (!node.parent) {
            }
            return node
        }
        return null
    }

    public loadNode(prefabPath: string, f: (n: cc.Node) => void, index: number = 0) {
        let name = prefabPath + "[" + index + "]"
        let n = this.getNodeFromPool(name)
        if (n) {
            if (IsDebug()) {
                cc.log("[Pool] getNodeFromPool: ", name)
            }
            f(n)
        } else {
            cc.loader.loadRes(prefabPath, cc.Prefab, (err: Error, res: cc.Prefab) => {
                if (err) { cc.error(err) }
                let n = cc.instantiate(res)
                let c = n.getComponent(PoolComponent)
                if (c == null) {
                    c = n.addComponent(PoolComponent)
                }

                {
                    let ps = n.getComponent(cc.ParticleSystem)
                    if (ps) {
                        ps.autoRemoveOnFinish = true
                        let oldFunc = ps._finishedSimulation
                        ps._finishedSimulation = function () {
                            ps.autoRemoveOnFinish = false
                            oldFunc.call(ps)
                            c.putBack()
                        }
                    }
                }
                c.prefabPath = name
                if (IsDebug()) {
                    cc.log("[Pool] loadRes: ", c.name)
                }
                f(n)
            })
        }
    }
}

export class PoolComponent extends cc.Component {
    prefabPath: string = ""

    constructor() {
        super()
    }

    onDestroy() {
    }

    putBack() {
        if (IsDebug()) {
            cc.log("[Pool] putBack: ", this.prefabPath)
        }
        //this.node.getComponentsInChildren(cc.ParticleSystem).forEach((ps: cc.ParticleSystem) => { })
        this.node.parent.removeChild(this.node, false)
        NodePool.getInstance().putNodeIntoPool(this.prefabPath, this.node)
    }
}